/*
    Copyright 2010 Barnet Wagman

    Licensed under the Apache License, Version 2.0 (the "License");
    you may not use this file except in compliance with the License.
    You may obtain a copy of the License at

        http://www.apache.org/licenses/LICENSE-2.0

    Unless required by applicable law or agreed to in writing, software
    distributed under the License is distributed on an "AS IS" BASIS,
    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    See the License for the specific language governing permissions and
    limitations under the License.
 */

package com.norbl.util.ec2;

import com.xerox.amazonws.ec2.*;
import java.util.*;

/**
 *
 * @author Barnet Wagman
 */
public class Ec2Ops {

    private Jec2 jec2;

    private String awsAccessID;
    private String awsSecretKey;

    public Ec2Ops(String awsAccessID,String awsSecretKey) {
        this.awsAccessID = awsAccessID;
        this.awsSecretKey = awsSecretKey;
        jec2 = new Jec2(awsAccessID, awsSecretKey, true);
    }

    public Ec2Ops cleanClone() {
        return(new Ec2Ops(awsAccessID, awsSecretKey));
    }

        /**
         * 
         * @param instanceType
         * @param imageID
         * @param kernelID
         * @param nInstances
         * @param zone
         * @param userData
         * @return instance IDs
         * @throws EC2Exception
         */
    public List<ReservationDescription.Instance> requestInstances(
                                            InstanceType instanceType,
                                            String imageID,
                                            String kernelID,
                                            int nInstances,
                                            String zone,
                                            String userData)
        throws EC2Exception {

        List<String> securityGroups = new ArrayList<String>();
                // ^ empty list of security definitions.

        ReservationDescription rd =
                jec2.runInstances(imageID,
                                    nInstances, // minCount
                                    nInstances, // maxCount
                                    securityGroups,
                                    userData,
                                    null, // key name
                                    true, // publidAddr
                                    instanceType,
                                    zone, // availbility zone
                                    kernelID, // kernel ID
                                    null, // ramdisk ID
                                    null // bdMaps
                                   );
        return( getInstances(rd) );
    }

    public void terminateInstances(List<String> instanceIDs)
        throws EC2Exception {
        
        if (instanceIDs != null )
            jec2.terminateInstances(instanceIDs);
    }

    public void terminateInstance(String instanceID)
        throws EC2Exception {

        if (instanceID != null )
            jec2.terminateInstances(new String[] { instanceID });
    }

    public void rebootInstance(String instanceID) throws EC2Exception {

        if (instanceID != null ) {
            jec2.rebootInstances(new String[] {instanceID} );
        }
    }

    public void rebootInstances(List<String> instanceIDs) throws EC2Exception {

        if (instanceIDs != null ) {
            jec2.rebootInstances(instanceIDs);
        }
    }

        /** Gets the states of all instances owned by the user.
         *
         * @return hash table of states keyed by instance ID.
         * @throws EC2Exception
         */
    public HashMap<String,String> getInstanceStates() throws EC2Exception {

        List<ReservationDescription> rds =
                    jec2.describeInstances(new String[] {});

        List<ReservationDescription.Instance> ins =
                new ArrayList<ReservationDescription.Instance>();

        for ( ReservationDescription rd : rds ) {
            ins.addAll(rd.getInstances());
        }

        HashMap<String,String> ht = new HashMap<String, String>();
        for ( ReservationDescription.Instance i : ins ) {
            ht.put(i.getInstanceId(),i.getState());
        }
        return(ht);
    }

        /** @return instance description objects for all instances
         *  owned by the user.
         * 
         * @return instance description objects.
         * @throws EC2Exception
         */
    public List<ReservationDescription.Instance> getInstances()
        throws EC2Exception {

        List<ReservationDescription> rds =
                    jec2.describeInstances(new String[] {});

        List<ReservationDescription.Instance> ins =
                new ArrayList<ReservationDescription.Instance>();

        for ( ReservationDescription rd : rds ) {
            ins.addAll(rd.getInstances());
        }

        return(ins);
    }

        /** Gets the instance IDs of all instances owned by the user.
         * 
         * @return instance IDs.
         * @throws EC2Exception
         */
    public List<String> getInstanceIDs() throws EC2Exception {

        List<String> iids = new ArrayList<String>();
        List<ReservationDescription> rds =
                    jec2.describeInstances(new String[] {});

        List<ReservationDescription.Instance> ins =
                new ArrayList<ReservationDescription.Instance>();

        for ( ReservationDescription rd : rds ) {
            ins.addAll(rd.getInstances());
        }

        for ( ReservationDescription.Instance i : ins ) {
            iids.add(i.getInstanceId());
        }
        return(iids);
    }

        // ---------------------------------------------

    static String getInstanceTypesString() {
        StringBuilder b = new StringBuilder();
        for ( InstanceType ins : InstanceType.values() ) {
            b.append(ins.getTypeId() + " ");
        }
        return(b.toString().trim());
    }

    public static List<String> getInstanceIDs(
                        List<ReservationDescription.Instance> ris) {

        List<String> instanceIDs = new ArrayList<String>();

        if ( ris == null ) return(instanceIDs);

        for ( ReservationDescription.Instance ri : ris ) {
            instanceIDs.add(ri.getInstanceId());
        }

        return(instanceIDs);
    }

    static List<String> getInstanceIDs(ReservationDescription rd) {

        List<String> instanceIDs = new ArrayList<String>();

        if ( rd != null ) {
            List<ReservationDescription.Instance> instances =
                rd.getInstances();

            for ( ReservationDescription.Instance ins : instances ) {
                instanceIDs.add(ins.getInstanceId());
            }
        }
        return(instanceIDs);
    }

    static List<ReservationDescription.Instance> getInstances(
                                        ReservationDescription rd) {

        if ( rd != null ) return( rd.getInstances() );
        else return(null);
    }

    public Jec2 getJec2() { return(jec2); }
}
